<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue';
import { useQuasar } from 'quasar';
import * as Tesseract from 'tesseract.js';

const $q = useQuasar();

// 上传的图像
const imageFile = ref<File | null>(null);
const previewUrl = ref<string>('');
const processedImageUrl = ref<string>('');

// 识别配置
const recognitionMode = ref('standard'); // 'standard', 'handwritten'

// 是否显示推荐提示
const showRecommendation = ref(true);

// 显示推荐提示
onMounted(() => {
  $q.dialog({
    title: '提示',
    message: '如果您需要识别手写算式，我们推荐使用微信小程序"小猿口算"，识别准确率更高！',
    persistent: true,
    ok: {
      color: 'primary',
      label: '知道了'
    }
  });
});

// 关闭推荐提示
const closeRecommendation = () => {
  showRecommendation.value = false;
};

// 扫描状态
const scanning = ref(false);
const scanProgress = ref(0);

// 识别的结果
const recognizedResults = reactive<{
  problems: Array<{ expression: string; studentAnswer: number | null; correctAnswer: number | null; isCorrect: boolean }>;
  correctCount: number;
  totalCount: number;
}>({
  problems: [],
  correctCount: 0,
  totalCount: 0
});

// 扫描记录
const scanHistory = ref<Array<{
  date: string;
  correctCount: number;
  totalCount: number;
  problems: Array<{ expression: string; studentAnswer: number | null; correctAnswer: number | null; isCorrect: boolean }>;
}>>([]);

// 多模型配置
const multiModelEnabled = ref(true);

// 用户校正数据
const userCorrections = ref<Array<{
  originalExpression: string;
  correctedExpression: string;
  timestamp: number;
}>>([]);

// 当前选中的问题索引
const selectedProblemIndex = ref<number>(-1);

// 用于校正输入
const correctionInput = ref('');

// 加载保存的校正数据
const loadUserCorrections = () => {
  try {
    const savedCorrections = localStorage.getItem('userCorrections');
    if (savedCorrections) {
      userCorrections.value = JSON.parse(savedCorrections);
    }
  } catch (e) {
    console.error('加载用户校正数据失败:', e);
  }
};

// 初始加载
loadUserCorrections();

// 处理图像上传
const handleImageUpload = (event: Event) => {
  const target = event.target as HTMLInputElement;
  const files = target.files;
  
  if (files && files.length > 0) {
    // 释放之前的URL资源
    if (previewUrl.value) {
      URL.revokeObjectURL(previewUrl.value);
    }
    if (processedImageUrl.value) {
      URL.revokeObjectURL(processedImageUrl.value);
    }
    
    imageFile.value = files[0];
    previewUrl.value = URL.createObjectURL(files[0]);
    processedImageUrl.value = '';
  }
};

// 处理文件选择
const handleFileSelected = (file: File) => {
  if (file) {
    // 释放之前的URL资源
    if (previewUrl.value) {
      URL.revokeObjectURL(previewUrl.value);
    }
    if (processedImageUrl.value) {
      URL.revokeObjectURL(processedImageUrl.value);
    }
    
    imageFile.value = file;
    previewUrl.value = URL.createObjectURL(file);
    processedImageUrl.value = '';
  }
};

// 捕获相机图像
const captureImage = () => {
  // 创建一个文件输入来触发相机
  const input = document.createElement('input');
  input.type = 'file';
  input.accept = 'image/*';
  input.capture = 'environment';
  
  input.onchange = (e) => handleImageUpload(e);
  input.click();
};

// 清除当前图片
const clearImage = () => {
  // 释放之前的URL资源
  if (previewUrl.value) {
    URL.revokeObjectURL(previewUrl.value);
  }
  if (processedImageUrl.value) {
    URL.revokeObjectURL(processedImageUrl.value);
  }
  
  imageFile.value = null;
  previewUrl.value = '';
  processedImageUrl.value = '';
  recognizedResults.problems = [];
  recognizedResults.correctCount = 0;
  recognizedResults.totalCount = 0;
};

// 图像预处理：增强对比度、自适应阈值、降噪、倾斜校正等操作以提高手写识别率
const preprocessImage = async (imageSource: File | string): Promise<string> => {
  return new Promise((resolve) => {
    const img = new Image();
    img.onload = () => {
      // 创建Canvas
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      
      if (!ctx) {
        resolve(imageSource instanceof File ? URL.createObjectURL(imageSource) : imageSource);
        return;
      }
      
      // 设置Canvas大小
      canvas.width = img.width;
      canvas.height = img.height;
      
      // 绘制原始图像
      ctx.drawImage(img, 0, 0);
      
      // 获取图像数据
      const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
      const data = imageData.data;
      
      // 第一步：使用高斯模糊降噪
      const gaussBlurredData = applyGaussianBlur(data, canvas.width, canvas.height, 1);
      
      // 第二步：自适应阈值处理
      const binaryData = applyAdaptiveThreshold(gaussBlurredData, canvas.width, canvas.height, 15, 2);
      
      // 第三步：形态学操作 - 膨胀和腐蚀处理增强笔画
      const morphedData = applyMorphologicalOps(binaryData, canvas.width, canvas.height);
      
      // 将处理后的数据放回Canvas
      for (let i = 0; i < data.length; i++) {
        data[i] = morphedData[i];
      }
      ctx.putImageData(imageData, 0, 0);
      
      // 尝试检测并校正倾斜（简化版）
      // 注意：完整的倾斜校正需要更复杂的算法，这里只是简化实现
      const correctedCanvas = detectAndCorrectSkew(canvas);
      
      // 转为URL返回
      const processedUrl = correctedCanvas.toDataURL('image/png');
      resolve(processedUrl);
    };
    
    img.src = imageSource instanceof File ? URL.createObjectURL(imageSource) : imageSource;
  });
};

// 高斯模糊函数
const applyGaussianBlur = (data: Uint8ClampedArray, width: number, height: number, radius: number): Uint8ClampedArray => {
  // 创建输出数组
  const output = new Uint8ClampedArray(data.length);
  
  // 高斯核大小
  const size = radius * 2 + 1;
  // 简单高斯核生成（完整实现会更复杂）
  const kernel = generateGaussianKernel(size, radius / 2);
  
  // 对每个像素应用卷积
  for (let y = 0; y < height; y++) {
    for (let x = 0; x < width; x++) {
      let r = 0, g = 0, b = 0, a = 0;
      let weightSum = 0;
      
      // 应用卷积核
      for (let ky = -radius; ky <= radius; ky++) {
        for (let kx = -radius; kx <= radius; kx++) {
          const pixelX = Math.min(Math.max(x + kx, 0), width - 1);
          const pixelY = Math.min(Math.max(y + ky, 0), height - 1);
          const idx = (pixelY * width + pixelX) * 4;
          
          const weight = kernel[(ky + radius) * size + (kx + radius)];
          
          r += data[idx] * weight;
          g += data[idx + 1] * weight;
          b += data[idx + 2] * weight;
          a += data[idx + 3] * weight;
          
          weightSum += weight;
        }
      }
      
      // 设置输出像素
      const outIdx = (y * width + x) * 4;
      output[outIdx] = r / weightSum;
      output[outIdx + 1] = g / weightSum;
      output[outIdx + 2] = b / weightSum;
      output[outIdx + 3] = a / weightSum;
    }
  }
  
  return output;
};

// 生成高斯核
const generateGaussianKernel = (size: number, sigma: number): number[] => {
  const kernel = new Array(size * size);
  const center = Math.floor(size / 2);
  
  for (let y = 0; y < size; y++) {
    for (let x = 0; x < size; x++) {
      const dx = x - center;
      const dy = y - center;
      // 高斯函数
      kernel[y * size + x] = Math.exp(-(dx * dx + dy * dy) / (2 * sigma * sigma));
    }
  }
  
  // 归一化
  const sum = kernel.reduce((sum, val) => sum + val, 0);
  return kernel.map(val => val / sum);
};

// 自适应阈值二值化处理
const applyAdaptiveThreshold = (data: Uint8ClampedArray, width: number, height: number, windowSize: number, C: number): Uint8ClampedArray => {
  // 创建输出数组
  const output = new Uint8ClampedArray(data.length);
  const halfWindow = Math.floor(windowSize / 2);
  
  for (let y = 0; y < height; y++) {
    for (let x = 0; x < width; x++) {
      // 计算当前窗口内的平均值
      let sum = 0;
      let count = 0;
      
      for (let wy = -halfWindow; wy <= halfWindow; wy++) {
        for (let wx = -halfWindow; wx <= halfWindow; wx++) {
          const pixelX = Math.min(Math.max(x + wx, 0), width - 1);
          const pixelY = Math.min(Math.max(y + wy, 0), height - 1);
          const idx = (pixelY * width + pixelX) * 4;
          
          // 使用灰度值
          const gray = data[idx] * 0.299 + data[idx + 1] * 0.587 + data[idx + 2] * 0.114;
          sum += gray;
          count++;
        }
      }
      
      // 计算阈值
      const threshold = (sum / count) - C;
      
      // 应用阈值
      const idx = (y * width + x) * 4;
      const gray = data[idx] * 0.299 + data[idx + 1] * 0.587 + data[idx + 2] * 0.114;
      const value = gray < threshold ? 0 : 255;
      
      output[idx] = value;
      output[idx + 1] = value;
      output[idx + 2] = value;
      output[idx + 3] = data[idx + 3]; // 保持Alpha通道不变
    }
  }
  
  return output;
};

// 形态学操作 - 膨胀和腐蚀
const applyMorphologicalOps = (data: Uint8ClampedArray, width: number, height: number): Uint8ClampedArray => {
  // 先膨胀后腐蚀（闭运算）增强笔画连接性
  const dilated = dilate(data, width, height, 1);
  const closed = erode(dilated, width, height, 1);
  return closed;
};

// 膨胀操作
const dilate = (data: Uint8ClampedArray, width: number, height: number, radius: number): Uint8ClampedArray => {
  const output = new Uint8ClampedArray(data.length);
  
  for (let y = 0; y < height; y++) {
    for (let x = 0; x < width; x++) {
      let maxValue = 0;
      
      for (let ky = -radius; ky <= radius; ky++) {
        for (let kx = -radius; kx <= radius; kx++) {
          const pixelX = Math.min(Math.max(x + kx, 0), width - 1);
          const pixelY = Math.min(Math.max(y + ky, 0), height - 1);
          const idx = (pixelY * width + pixelX) * 4;
          
          // 寻找最大值（膨胀）
          maxValue = Math.max(maxValue, data[idx]);
        }
      }
      
      const outIdx = (y * width + x) * 4;
      output[outIdx] = maxValue;
      output[outIdx + 1] = maxValue;
      output[outIdx + 2] = maxValue;
      output[outIdx + 3] = data[(y * width + x) * 4 + 3]; // 保持Alpha通道不变
    }
  }
  
  return output;
};

// 腐蚀操作
const erode = (data: Uint8ClampedArray, width: number, height: number, radius: number): Uint8ClampedArray => {
  const output = new Uint8ClampedArray(data.length);
  
  for (let y = 0; y < height; y++) {
    for (let x = 0; x < width; x++) {
      let minValue = 255;
      
      for (let ky = -radius; ky <= radius; ky++) {
        for (let kx = -radius; kx <= radius; kx++) {
          const pixelX = Math.min(Math.max(x + kx, 0), width - 1);
          const pixelY = Math.min(Math.max(y + ky, 0), height - 1);
          const idx = (pixelY * width + pixelX) * 4;
          
          // 寻找最小值（腐蚀）
          minValue = Math.min(minValue, data[idx]);
        }
      }
      
      const outIdx = (y * width + x) * 4;
      output[outIdx] = minValue;
      output[outIdx + 1] = minValue;
      output[outIdx + 2] = minValue;
      output[outIdx + 3] = data[(y * width + x) * 4 + 3]; // 保持Alpha通道不变
    }
  }
  
  return output;
};

// 倾斜检测和校正（简化版）
const detectAndCorrectSkew = (canvas: HTMLCanvasElement): HTMLCanvasElement => {
  // 注意：实际的倾斜校正需要更复杂的算法（霍夫变换等）
  // 这里仅提供一个框架，实际生产环境需要更复杂的实现
  
  // 创建一个新的Canvas用于输出
  const outputCanvas = document.createElement('canvas');
  outputCanvas.width = canvas.width;
  outputCanvas.height = canvas.height;
  const outputCtx = outputCanvas.getContext('2d');
  
  if (!outputCtx) return canvas;
  
  // 在此进行倾斜检测和校正
  // 简化实现：直接复制原始Canvas内容
  outputCtx.drawImage(canvas, 0, 0);
  
  // 返回校正后的Canvas
  return outputCanvas;
};

// 开始扫描识别
const startScan = async () => {
  if (!imageFile.value) {
    $q.notify({
      message: '请先上传图片',
      color: 'negative'
    });
    return;
  }
  
  scanning.value = true;
  scanProgress.value = 0;
  
  try {
    $q.notify({
      message: '正在预处理图像并识别，请稍候...',
      color: 'info'
    });
    
    // 预处理图像
    processedImageUrl.value = await preprocessImage(imageFile.value);
    
    if (recognitionMode.value === 'handwritten') {
      // 手写模式：使用分割识别方法
      await recognizeWithSegmentation(processedImageUrl.value);
    } else {
      // 标准模式：使用整体识别
      await recognizeStandard(processedImageUrl.value);
    }
    
    $q.notify({
      message: '识别完成!',
      color: 'positive'
    });
  } catch (error) {
    console.error('识别错误:', error);
    $q.notify({
      message: '识别过程发生错误',
      color: 'negative'
    });
  } finally {
    scanning.value = false;
  }
};

// 标准识别方法
const recognizeStandard = async (imageSource: string | File) => {
    // 配置Tesseract识别选项
    const tessOptions = {
      logger: (m: any) => {
        if (m.status === 'recognizing text') {
          scanProgress.value = Math.round(m.progress * 100);
        }
      },
      tessedit_char_whitelist: '0123456789+-×÷=', // 限制字符集
      tessedit_pageseg_mode: '6',  // 默认为单列文本
      preserve_interword_spaces: '1',
      tessjs_create_hocr: '0',
      tessjs_create_tsv: '0',
    };
    
    // 识别图像
    const result = await Tesseract.recognize(
      imageSource,
      'chi_sim+eng',
      tessOptions
    );
    
    // 处理识别结果，提取算式和答案
    processScanResult(result.data.text);
};

// 分割识别方法（针对手写优化）
const recognizeWithSegmentation = async (imageSource: string) => {
  try {
    // 1. 加载图像到Canvas
    const img = new Image();
    await new Promise((resolve, reject) => {
      img.onload = resolve;
      img.onerror = reject;
      img.src = imageSource;
    });
    
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    if (!ctx) throw new Error('无法获取canvas上下文');
    
    canvas.width = img.width;
    canvas.height = img.height;
    ctx.drawImage(img, 0, 0);
    
    // 2. 尝试分割找到潜在的算式区域（这里使用简化方法，实际中可用连通区域分析）
    const regions = await findPotentialExpressionRegions(canvas);
    
    if (multiModelEnabled.value && regions.length > 0) {
      // 多模型融合处理
      const recognizedText = await multiModelRecognition(regions, canvas);
      processScanResult(recognizedText.join('\n'));
    } else {
      // 3. 对每个区域单独进行识别
      const recognizedText = await recognizeRegions(regions, canvas);
      
      // 4. 处理识别结果
      processScanResult(recognizedText.join('\n'));
    }
  } catch (error) {
    console.error('分割识别失败:', error);
    // 降级到标准识别
    await recognizeStandard(imageSource);
  }
};

// 查找潜在的算式区域
const findPotentialExpressionRegions = async (canvas: HTMLCanvasElement): Promise<Array<{x: number, y: number, width: number, height: number}>> => {
  const ctx = canvas.getContext('2d');
  if (!ctx) return [];
  
  // 获取图像数据
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  const data = imageData.data;
  
  // 简化版：基于行投影的分割
  // 计算每行的黑色像素数量
  const rowProjection = new Array(canvas.height).fill(0);
  for (let y = 0; y < canvas.height; y++) {
    for (let x = 0; x < canvas.width; x++) {
      const idx = (y * canvas.width + x) * 4;
      // 如果是黑色像素（算式像素）
      if (data[idx] < 128) {
        rowProjection[y]++;
      }
    }
  }
  
  // 找出行分割点
  const rowSegments = [];
  let inSegment = false;
  let segmentStart = 0;
  
  // 设定阈值，当一行黑色像素数超过此值，认为是算式所在行
  const threshold = canvas.width * 0.01; // 1%像素黑色即可能是算式行
  
  for (let y = 0; y < canvas.height; y++) {
    if (rowProjection[y] > threshold && !inSegment) {
      // 开始一个新行段
      inSegment = true;
      segmentStart = y;
    } else if ((rowProjection[y] <= threshold || y === canvas.height - 1) && inSegment) {
      // 结束当前行段
      inSegment = false;
      rowSegments.push({ start: segmentStart, end: y });
    }
  }
  
  // 将行段转换为矩形区域
  const regions = rowSegments.map(segment => {
    // 行高
    const height = segment.end - segment.start;
    
    // 如果行高过小，可能是噪声，跳过
    if (height < 10) return null;
    
    return {
      x: 0,                  // 开始于画布左侧
      y: segment.start,      // 行开始位置
      width: canvas.width,   // 宽度为画布整宽
      height: height         // 行高
    };
  }).filter(Boolean) as Array<{ x: number; y: number; width: number; height: number }>;
  
  return regions;
};

// 识别分割后的区域
const recognizeRegions = async (regions: Array<{x: number, y: number, width: number, height: number}>, canvas: HTMLCanvasElement): Promise<string[]> => {
  if (regions.length === 0) return [];
  
  const results = [];
  
  for (let i = 0; i < regions.length; i++) {
    const region = regions[i];
    
    // 创建一个新Canvas保存区域图像
    const regionCanvas = document.createElement('canvas');
    const regionCtx = regionCanvas.getContext('2d');
    if (!regionCtx) continue;
    
    // 设置区域Canvas大小
    regionCanvas.width = region.width;
    regionCanvas.height = region.height;
    
    // 复制区域图像
    regionCtx.drawImage(
      canvas,
      region.x, region.y, region.width, region.height,
      0, 0, region.width, region.height
    );
    
    // 为每个区域设置优化的Tesseract配置
    const tessOptions = {
      logger: (m: any) => {
        if (m.status === 'recognizing text') {
          // 更新总体进度
          scanProgress.value = Math.round(((i / regions.length) + (m.progress / regions.length)) * 100);
        }
      },
      tessedit_char_whitelist: '0123456789+-×÷=', // 限制字符集
      tessedit_pageseg_mode: '7',  // 将每行视为单行文本
      preserve_interword_spaces: '1',
      tessjs_create_hocr: '0',
      tessjs_create_tsv: '0',
    };
    
    // 对区域进行识别
    try {
      const result = await Tesseract.recognize(
        regionCanvas.toDataURL('image/png'),
        'chi_sim+eng',
        tessOptions
      );
      
      results.push(result.data.text.trim());
    } catch (e) {
      console.warn(`区域 ${i+1} 识别失败:`, e);
    }
  }
  
  return results;
};

// 多模型融合识别
const multiModelRecognition = async (regions: Array<{x: number, y: number, width: number, height: number}>, canvas: HTMLCanvasElement): Promise<string[]> => {
  if (regions.length === 0) return [];
  
  const results = [];
  
  for (let i = 0; i < regions.length; i++) {
    const region = regions[i];
    
    // 创建一个新Canvas保存区域图像
    const regionCanvas = document.createElement('canvas');
    const regionCtx = regionCanvas.getContext('2d');
    if (!regionCtx) continue;
    
    // 设置区域Canvas大小
    regionCanvas.width = region.width;
    regionCanvas.height = region.height;
    
    // 复制区域图像
    regionCtx.drawImage(
      canvas,
      region.x, region.y, region.width, region.height,
      0, 0, region.width, region.height
    );
    
    // 多处理方式并行识别
    const recognitionPromises = [];
    
    // 方法1: 标准模式
    const tessStandard = {
      logger: (m: any) => {
        if (m.status === 'recognizing text') {
          scanProgress.value = Math.round(((i / regions.length) + (m.progress / regions.length / 3)) * 100);
        }
      },
      tessedit_char_whitelist: '0123456789+-×÷=',
      tessedit_pageseg_mode: '7', // 单行文本
      preserve_interword_spaces: '1',
    };
    
    // 方法2: 字符级模式
    const tessCharLevel = {
      logger: (m: any) => {
        if (m.status === 'recognizing text') {
          scanProgress.value = Math.round(((i / regions.length) + (1/3) + (m.progress / regions.length / 3)) * 100);
        }
      },
      tessedit_char_whitelist: '0123456789+-×÷=',
      tessedit_pageseg_mode: '10', // 单个字符模式
      preserve_interword_spaces: '0',
    };
    
    // 方法3: 高精度模式 
    const tessHighPrecision = {
      logger: (m: any) => {
        if (m.status === 'recognizing text') {
          scanProgress.value = Math.round(((i / regions.length) + (2/3) + (m.progress / regions.length / 3)) * 100);
        }
      },
      tessedit_char_whitelist: '0123456789+-×÷=',
      tessedit_pageseg_mode: '6',
      tessjs_create_hocr: '1', // 生成HOCR以便提取位置信息
      tessjs_create_tsv: '1',
    };
    
    // 应用不同的图像处理方式
    const regionDataUrl = regionCanvas.toDataURL('image/png');
    
    // 进行多模型识别
    recognitionPromises.push(
      Tesseract.recognize(regionDataUrl, 'chi_sim+eng', tessStandard)
        .then(result => ({ text: result.data.text, confidence: result.data.confidence, type: 'standard' }))
        .catch(() => ({ text: '', confidence: 0, type: 'standard' }))
    );
    
    recognitionPromises.push(
      Tesseract.recognize(regionDataUrl, 'chi_sim+eng', tessCharLevel)
        .then(result => ({ text: result.data.text, confidence: result.data.confidence, type: 'char' }))
        .catch(() => ({ text: '', confidence: 0, type: 'char' }))
    );
    
    // 应用用户校正增强
    recognitionPromises.push(
      Tesseract.recognize(regionDataUrl, 'chi_sim+eng', tessHighPrecision)
        .then(result => ({ text: result.data.text, confidence: result.data.confidence, type: 'high' }))
        .catch(() => ({ text: '', confidence: 0, type: 'high' }))
    );
    
    try {
      // 等待所有识别完成
      const recognitionResults = await Promise.all(recognitionPromises);
      
      // 多模型结果融合
      const bestResult = selectBestResult(recognitionResults);
      results.push(bestResult);
      
    } catch (e) {
      console.warn(`区域 ${i+1} 多模型识别失败:`, e);
    }
  }
  
  return results;
};

// 选择最佳结果
const selectBestResult = (results: Array<{text: string, confidence: number, type: string}>): string => {
  // 过滤掉空结果
  const validResults = results.filter(r => r.text.trim().length > 0);
  if (validResults.length === 0) return '';
  
  // 对每个结果应用正则表达式过滤，只保留匹配算式的结果
  const matchedResults = validResults.map(result => {
    const text = result.text;
    let hasMatch = false;
    
    // 检查是否包含算式
    for (const pattern of [
      /(\d+)\s*([+\-×÷])\s*(\d+)\s*=\s*(\d*)/,
      /(\d+)\s*[xX*]\s*(\d+)\s*=\s*(\d*)/,
      /(\d+)\s*[\/÷]\s*(\d+)\s*=\s*(\d*)/
    ]) {
      if (pattern.test(text)) {
        hasMatch = true;
        break;
      }
    }
    
    return {
      ...result,
      hasMatch
    };
  });
  
  // 优先返回匹配算式的结果
  const matchingResults = matchedResults.filter(r => r.hasMatch);
  
  if (matchingResults.length > 0) {
    // 如果有多个匹配结果，选择置信度最高的
    matchingResults.sort((a, b) => b.confidence - a.confidence);
    
    // 应用用户校正知识
    const enhancedResult = applyUserCorrections(matchingResults[0].text);
    return enhancedResult;
  }
  
  // 如果没有匹配结果，返回置信度最高的文本
  validResults.sort((a, b) => b.confidence - a.confidence);
  return validResults[0].text;
};

// 应用用户校正知识
const applyUserCorrections = (text: string): string => {
  // 简单实现：直接返回原文本
  // 实际项目中，可以基于以往的校正记录做更复杂的处理
  return text;
};

// 优化算式提取正则表达式
const processScanResult = (text: string) => {
  console.log('OCR识别结果:', text); // 调试输出
  
  const problems: Array<{ expression: string; studentAnswer: number | null; correctAnswer: number | null; isCorrect: boolean }> = [];
  let correctCount = 0;
  
  // 增强正则表达式：支持更多的格式变体和噪声处理
  // 处理可能出现的符号误识别和格式问题
  const regexPatterns = [
    /(\d+)\s*([+\-×÷])\s*(\d+)\s*=\s*(\d*)/g,        // 标准格式
    /(\d+)\s*[xX*]\s*(\d+)\s*=\s*(\d*)/g,            // × 可能被识别为 x, X 或 *
    /(\d+)\s*[\/÷]\s*(\d+)\s*=\s*(\d*)/g,            // ÷ 可能被识别为 /
    /(\d+)\s*[\+]\s*(\d+)\s*=\s*(\d*)/g,             // + 可能有额外空格
    /(\d+)\s*[\-]\s*(\d+)\s*=\s*(\d*)/g              // - 可能有额外空格
  ];
  
  // 遍历每一种模式来处理可能的识别变体
  for (const regex of regexPatterns) {
    let match;
  while ((match = regex.exec(text)) !== null) {
      // 从匹配结果获取数字和运算符
    const num1 = parseInt(match[1], 10);
      
      // 根据不同正则获取运算符和第二个数字
      let operator, num2, studentAnswer;
      
      if (match.length === 4) {
        // 处理特殊格式情况，如 5*3=15 的模式
        if (regex.source.includes('[xX*]')) {
          operator = '×';
        } else if (regex.source.includes('[\/÷]')) {
          operator = '÷';
        } else if (regex.source.includes('[\+]')) {
          operator = '+';
        } else if (regex.source.includes('[\-]')) {
          operator = '-';
        }
        num2 = parseInt(match[2], 10);
        studentAnswer = match[3] ? parseInt(match[3], 10) : null;
      } else {
        // 标准格式
        operator = match[2];
        num2 = parseInt(match[3], 10);
        studentAnswer = match[4] ? parseInt(match[4], 10) : null;
      }
    
    // 计算正确答案
    let correctAnswer;
    switch (operator) {
      case '+':
        correctAnswer = num1 + num2;
        break;
      case '-':
        correctAnswer = num1 - num2;
        break;
      case '×':
        correctAnswer = num1 * num2;
        break;
      case '÷':
          correctAnswer = num2 !== 0 ? Math.floor(num1 / num2) : null; // 整数除法
        break;
      default:
        correctAnswer = null;
    }
    
    const isCorrect = studentAnswer === correctAnswer;
    
    if (isCorrect) {
      correctCount++;
    }
    
      // 避免重复添加同一道题
      const expressionKey = `${num1}${operator}${num2}=${studentAnswer || ''}`;
      const isDuplicate = problems.some(p => p.expression === expressionKey);
      
      if (!isDuplicate) {
    problems.push({
          expression: expressionKey,
      studentAnswer,
      correctAnswer,
      isCorrect
    });
      }
    }
  }
  
  // 保存识别结果
  recognizedResults.problems = problems;
  recognizedResults.correctCount = correctCount;
  recognizedResults.totalCount = problems.length;
  
  // 添加到历史记录
  if (problems.length > 0) {
    scanHistory.value.unshift({
      date: new Date().toLocaleString(),
      correctCount,
      totalCount: problems.length,
      problems: [...problems]
    });
  }
};

// 保存错题
const saveWrongProblems = () => {
  if (recognizedResults.problems.length === 0) {
    $q.notify({
      message: '没有可保存的题目',
      color: 'warning'
    });
    return;
  }
  
  // 仅筛选出错题
  const wrongProblems = recognizedResults.problems.filter(p => !p.isCorrect);
  
  if (wrongProblems.length === 0) {
    $q.notify({
      message: '恭喜！没有错题需要保存',
      color: 'positive'
    });
    return;
  }
  
  // 这里可以实现错题保存逻辑，如存储到本地存储
  localStorage.setItem('wrongProblems', JSON.stringify([
    ...JSON.parse(localStorage.getItem('wrongProblems') || '[]'),
    ...wrongProblems
  ]));
  
  $q.notify({
    message: `已保存 ${wrongProblems.length} 道错题`,
    color: 'info'
  });
};

// 用户校正问题
const correctProblem = (index: number, correctedExpression: string) => {
  if (index < 0 || index >= recognizedResults.problems.length) return;
  
  const problem = recognizedResults.problems[index];
  const originalExpression = problem.expression;
  
  // 解析校正后的表达式
  const regex = /(\d+)\s*([+\-×÷])\s*(\d+)\s*=\s*(\d*)/;
  const match = correctedExpression.match(regex);
  
  if (match) {
    const num1 = parseInt(match[1], 10);
    const operator = match[2];
    const num2 = parseInt(match[3], 10);
    const studentAnswer = match[4] ? parseInt(match[4], 10) : null;
    
    // 计算正确答案
    let correctAnswer;
    switch (operator) {
      case '+': correctAnswer = num1 + num2; break;
      case '-': correctAnswer = num1 - num2; break;
      case '×': correctAnswer = num1 * num2; break;
      case '÷': correctAnswer = num2 !== 0 ? Math.floor(num1 / num2) : null; break;
      default: correctAnswer = null;
    }
    
    // 更新问题
    recognizedResults.problems[index] = {
      expression: correctedExpression,
      studentAnswer,
      correctAnswer,
      isCorrect: studentAnswer === correctAnswer
    };
    
    // 重新计算正确题目数量
    recognizedResults.correctCount = recognizedResults.problems.filter(p => p.isCorrect).length;
    
    // 保存校正记录
    userCorrections.value.push({
      originalExpression,
      correctedExpression,
      timestamp: Date.now()
    });
    
    // 本地存储校正数据
    localStorage.setItem('userCorrections', JSON.stringify(userCorrections.value));
    
    // 提示用户
    $q.notify({
      message: '校正成功',
      color: 'positive',
      position: 'bottom'
    });
  } else {
    $q.notify({
      message: '表达式格式错误',
      color: 'negative',
      position: 'bottom'
    });
  }
};

// 应用校正
const applyCorrection = () => {
  if (selectedProblemIndex.value >= 0 && correctionInput.value) {
    correctProblem(selectedProblemIndex.value, correctionInput.value);
    correctionInput.value = '';
  } else {
    $q.notify({
      message: '请输入要校正的表达式',
      color: 'warning',
      position: 'bottom'
    });
  }
};

// 在data区域添加展开控制变量
const analysisExpanded = ref(true); // 设置结果分析模块默认展开
</script>

<template>
  <q-card flat bordered>
    <!-- 全局推荐提示框 -->
    <q-banner
      v-if="showRecommendation"
      rounded
      class="bg-primary text-white q-mb-md"
    >
      <template v-slot:avatar>
        <q-icon name="star" color="white" />
      </template>
      <span class="text-weight-bold">推荐使用：</span>
      微信小程序"小猿口算"，专业手写算式识别，准确率高达95%以上！
      <template v-slot:action>
        <q-btn flat color="white" label="知道了" @click="closeRecommendation" />
      </template>
    </q-banner>
    
    <q-card-section class="text-h6">
      智能批改系统
    </q-card-section>
    
    <!-- 手写模式下的详细推荐提示 -->
    <q-card-section v-if="recognitionMode === 'handwritten'" class="recommendation-section">
      <q-banner class="bg-primary text-white">
        <template v-slot:avatar>
          <q-icon name="lightbulb" color="white" />
        </template>
        <div class="text-subtitle2">推荐使用</div>
        <div class="text-body2 q-mt-sm">
          如果您需要更准确的手写算式识别，我们推荐使用微信小程序"小猿口算"。
          <br>
          小猿口算专注于手写算式识别，识别准确率更高，支持更多题型。
        </div>
        <template v-slot:action>
          <q-btn flat color="white" label="继续使用当前系统" @click="recognitionMode = 'standard'" />
        </template>
      </q-banner>
    </q-card-section>
    
    <q-card-section>
      <div class="row q-col-gutter-md">
        <!-- 图片上传/拍照区域 -->
        <div class="col-md-6 col-xs-12">
          <div class="text-subtitle2 q-mb-sm">上传或拍摄习题照片</div>
          
          <div class="image-upload-area q-pa-md q-mb-md">
            <div v-if="!previewUrl" class="upload-placeholder flex flex-center">
              <div class="text-center">
                <q-icon name="photo_camera" size="48px" color="grey-7" />
                <div class="text-grey-7 q-mt-sm">点击上传或拍照</div>
              </div>
            </div>
            <q-img
              v-else
              :src="processedImageUrl || previewUrl"
              class="upload-preview"
              fit="contain"
            />
          </div>
          
          <div class="row q-col-gutter-sm">
            <div class="col">
              <q-file
                v-model="imageFile"
                label="选择图片"
                filled
                dense
                accept="image/*"
                @update:model-value="handleFileSelected"
              >
                <template v-slot:prepend>
                  <q-icon name="attach_file" />
                </template>
              </q-file>
            </div>
          </div>
          
          <div class="row q-col-gutter-sm q-mt-sm">
            <div class="col">
              <q-btn
                color="primary"
                icon="photo_camera"
                label="拍照"
                dense
                @click="captureImage"
              />
              <q-btn
                color="negative"
                icon="delete"
                label="清除"
                dense
                class="q-ml-sm"
                @click="clearImage"
              />
            </div>
          </div>
          
          <div class="row q-mt-md">
            <div class="col-12">
              <q-option-group
                v-model="recognitionMode"
                :options="[
                  { label: '标准模式 (印刷体)', value: 'standard' },
                  { label: '手写模式 (预处理优化)', value: 'handwritten' }
                ]"
                color="primary"
                inline
              />
            </div>
            
            <div class="col-12 q-mt-sm" v-if="recognitionMode === 'handwritten'">
              <q-toggle
                v-model="multiModelEnabled"
                label="启用多模型融合识别（提高识别率）"
                color="primary"
              />
            </div>
          </div>
        </div>
        
        <!-- 识别结果区域 -->
        <div class="col-md-6 col-xs-12">
          <div class="text-subtitle2 q-mb-sm">识别结果</div>
          
          <!-- 添加未来功能提示 -->
          <q-banner dense class="bg-blue-1 text-blue-9 q-mb-md">
            <template v-slot:avatar>
              <q-icon name="info" color="info" />
            </template>
            页面数据仅为示例，未来升级后使用在线作答则可以参与统计。
          </q-banner>
          
          <div v-if="recognizedResults.problems.length === 0" class="no-results q-pa-md text-center">
            <q-icon name="search" size="48px" color="grey-5" />
            <div class="text-grey-6 q-mt-sm">
              {{ scanning ? '正在识别中...' : '未识别到任何题目' }}
            </div>
            
            <q-linear-progress
              v-if="scanning"
              :value="scanProgress / 100"
              class="q-mt-md"
              size="md"
              rounded
              stripe
              color="primary"
            />
          </div>
          
          <div v-else>
            <div class="result-summary q-mb-md">
              <q-chip outline color="primary">
                共识别到 {{ recognizedResults.totalCount }} 道题
              </q-chip>
              <q-chip outline :color="recognizedResults.correctCount === recognizedResults.totalCount ? 'positive' : 'warning'">
                正确: {{ recognizedResults.correctCount }} 道
              </q-chip>
              <q-chip outline color="negative" v-if="recognizedResults.totalCount > recognizedResults.correctCount">
                错误: {{ recognizedResults.totalCount - recognizedResults.correctCount }} 道
              </q-chip>
            </div>
            
            <q-list bordered separator>
              <q-item 
                v-for="(problem, index) in recognizedResults.problems" 
                :key="index"
                clickable
                @click="selectedProblemIndex = index"
                :active="selectedProblemIndex === index"
              >
                <q-item-section>
                  {{ problem.expression }}
                </q-item-section>
                <q-item-section side>
                  <q-icon
                    :name="problem.isCorrect ? 'check_circle' : 'cancel'"
                    :color="problem.isCorrect ? 'positive' : 'negative'"
                    size="24px"
                  />
                </q-item-section>
              </q-item>
            </q-list>
            
            <!-- 用户校正界面 -->
            <div class="q-mt-md" v-if="selectedProblemIndex >= 0">
              <q-card flat bordered class="q-pa-sm correction-card">
                <q-card-section class="q-pa-xs">
                  <div class="text-subtitle2">校正算式</div>
                  <q-input 
                    v-model="correctionInput" 
                    label="输入正确的算式" 
                    dense
                    filled 
                    :placeholder="recognizedResults.problems[selectedProblemIndex]?.expression || ''"
                    class="q-mt-sm"
                  />
                </q-card-section>
                <q-card-actions align="right">
                  <q-btn 
                    color="primary" 
                    label="应用校正" 
                    dense
                    @click="applyCorrection"
                  />
                  <q-btn 
                    color="grey" 
                    label="取消" 
                    dense
                    @click="selectedProblemIndex = -1; correctionInput = ''"
                  />
                </q-card-actions>
              </q-card>
            </div>
            
            <div class="q-mt-md">
              <q-btn color="primary" icon="save" label="保存错题" @click="saveWrongProblems" />
              <q-btn 
                color="info" 
                icon="edit" 
                label="校正" 
                class="q-ml-sm" 
                @click="selectedProblemIndex = selectedProblemIndex === -1 ? 0 : -1"
              />
            </div>
          </div>
        </div>
      </div>
    </q-card-section>
    
    <q-card-actions align="center">
      <q-btn 
        color="primary" 
        icon="scanner" 
        :label="scanning ? '识别中...' : '开始识别'" 
        :loading="scanning"
        @click="startScan" 
        :disable="!previewUrl || scanning"
      />
    </q-card-actions>
    
    <!-- 扫描历史 -->
    <q-expansion-item
      label="扫描历史"
      icon="history"
      header-class="text-primary"
      v-if="scanHistory.length > 0"
    >
      <q-card>
        <q-card-section>
          <!-- 添加未来功能提示 -->
          <q-banner dense class="bg-blue-1 text-blue-9 q-mb-md">
            <template v-slot:avatar>
              <q-icon name="info" color="info" />
            </template>
            页面数据仅为示例，未来升级后使用在线作答则可以参与统计。
          </q-banner>
          
          <q-list bordered separator>
            <q-item v-for="(record, index) in scanHistory" :key="index">
              <q-item-section>
                <q-item-label>{{ record.date }}</q-item-label>
                <q-item-label caption>
                  正确率: {{ Math.round((record.correctCount / record.totalCount) * 100) }}%
                  ({{ record.correctCount }}/{{ record.totalCount }})
                </q-item-label>
              </q-item-section>
              <q-item-section side>
                <q-btn flat round icon="visibility" color="primary" />
              </q-item-section>
            </q-item>
          </q-list>
        </q-card-section>
      </q-card>
    </q-expansion-item>
    
    <!-- 新增：结果分析模块 -->
    <q-expansion-item
      label="结果分析"
      icon="analytics"
      header-class="text-primary"
      v-model="analysisExpanded"
      default-opened
    >
      <q-card>
        <q-card-section>
          <!-- 添加未来功能提示 -->
          <q-banner class="bg-blue-1 text-blue-9 q-mb-md">
            <template v-slot:avatar>
              <q-icon name="info" color="info" size="24px" />
            </template>
            <span class="text-weight-medium" style="font-size: 16px;">页面数据仅为示例，未来升级后使用在线作答则可以参与统计。</span>
          </q-banner>
          
          <div class="row q-col-gutter-md">
            <div class="col-md-6 col-xs-12">
              <q-card flat bordered class="q-pa-md">
                <div class="text-subtitle2 q-mb-sm">正确率分析</div>
                <div class="text-center q-mt-md">
                  <q-circular-progress
                    show-value
                    font-size="12px"
                    :value="65"
                    size="120px"
                    :thickness="0.2"
                    color="primary"
                    track-color="grey-3"
                    class="q-ma-md"
                  >
                    65%
                  </q-circular-progress>
                  <div class="text-caption q-mt-sm">近期平均正确率</div>
                </div>
              </q-card>
            </div>
            
            <div class="col-md-6 col-xs-12">
              <q-card flat bordered class="q-pa-md">
                <div class="text-subtitle2 q-mb-sm">错题类型分布</div>
                <div class="q-mt-md">
                  <div v-for="(item, index) in [
                    { type: '加法', percent: 25 },
                    { type: '减法', percent: 45 },
                    { type: '乘法', percent: 20 },
                    { type: '除法', percent: 10 }
                  ]" :key="index" class="q-mb-sm">
                    <div class="row items-center">
                      <div class="col-5">{{item.type}}错误</div>
                      <div class="col-5">
                        <q-linear-progress
                          :value="item.percent/100"
                          :color="['primary', 'negative', 'warning', 'info'][index]"
                          size="10px"
                          rounded
                        />
                      </div>
                      <div class="col-2 text-right">{{item.percent}}%</div>
                    </div>
                  </div>
                </div>
              </q-card>
            </div>
          </div>
        </q-card-section>
      </q-card>
    </q-expansion-item>
    
    <!-- 用户校正统计 -->
    <q-expansion-item
      label="校正统计"
      icon="auto_fix_high"
      header-class="text-primary"
      v-if="userCorrections.length > 0"
    >
      <q-card>
        <q-card-section>
          <div class="text-subtitle2">您已校正 {{ userCorrections.length }} 次识别结果</div>
          <q-list bordered separator class="q-mt-md" style="max-height: 200px; overflow-y: auto;">
            <q-item v-for="(correction, index) in userCorrections.slice(0, 10)" :key="index">
              <q-item-section>
                <q-item-label>{{ correction.originalExpression }} → {{ correction.correctedExpression }}</q-item-label>
                <q-item-label caption>
                  {{ new Date(correction.timestamp).toLocaleString() }}
                </q-item-label>
              </q-item-section>
            </q-item>
          </q-list>
        </q-card-section>
      </q-card>
    </q-expansion-item>
  </q-card>
</template>

<style scoped>
.image-upload-area {
  border: 2px dashed #ccc;
  border-radius: 8px;
  cursor: pointer;
  min-height: 200px;
  position: relative;
  overflow: hidden;
}

.upload-placeholder {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.upload-preview {
  max-height: 300px;
}

.no-results {
  border: 1px solid #eee;
  border-radius: 8px;
  min-height: 200px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.result-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.correction-card {
  background-color: #f8f8f8;
  border-left: 4px solid #1976d2;
}

.recommendation-section {
  margin-bottom: 16px;
}

.recommendation-section .q-banner {
  border-radius: 8px;
}
</style> 